home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / Unsupported Libraries / QDUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-11  |  11.9 KB  |  484 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2.  **                                                                             **
  3.  **     Module:        QDUtils.c                                                 **
  4.  **                                                                          **
  5.  **                                                                          **
  6.  **     Purpose:     Utilities for creating Quickdraw windows and GWorlds     **
  7.  **                                                                          **
  8.  **     Copyright (C) 1992-1995 Apple Computer, Inc.  All rights reserved.     **
  9.  **                                                                          **
  10.  **                                                                          **
  11.  *****************************************************************************/
  12. #include <Script.h>
  13. #include <stdio.h>
  14.  
  15. #include <Memory.h>
  16. #include <Quickdraw.h>
  17. #include <QDOffscreen.h>
  18. #include <Windows.h>
  19.  
  20. #include "QD3D.h"
  21. #include "QDUtils.h"
  22.  
  23. /******************************************************************************
  24.  **                                                                             **
  25.  **                                    Macros                                     **
  26.  **                                                                             **
  27.  *****************************************************************************/
  28.  
  29. /* a bad hack macro */
  30. #ifndef GetMBarHeight
  31. #define GetMBarHeight() (* (short *) 0x0BAA)
  32. #endif
  33.  
  34. #define COPYRECT(srcRect, dstRect) {                             \
  35.             *(long *)(dstRect)     = *(long *)(srcRect);         \
  36.             ((long *)(dstRect))[1] = ((long *)(srcRect))[1];     \
  37.         }
  38.  
  39.  
  40. /******************************************************************************
  41.  **                                                                             **
  42.  **                            Forward Declarations                             **
  43.  **                                                                             **
  44.  *****************************************************************************/
  45.  
  46. /* 
  47.  * A BIG NOTE:
  48.  * The following functions really belong in application land but since we
  49.  * share them as common functions in our Escher test programs they are
  50.  * placed here into the Quickdraw library directory.  Escher applications
  51.  * should have similar functions that meet their own requirements.
  52.  */
  53.  
  54. static GDHandle GetGDeviceUsingDepth(
  55.     unsigned long    depth);
  56.  
  57. static GDHandle FindDeviceFromWindow(
  58.     WindowPtr         window,
  59.     PixMapHandle    gPixMap);
  60.  
  61. static void GetPortTopLeft(
  62.     CGrafPtr         port, 
  63.     Point             *topLeft);
  64.  
  65. static BitMap *BitsToMap(
  66.     BitMap             *bits);
  67.  
  68. static void CopyPixels_32(
  69.     GDHandle        device,
  70.     WindowPtr        window,
  71.     PixMapHandle    hPixMap);
  72.  
  73. /******************************************************************************
  74.  **                                                                             **
  75.  **                                    Functions                                 **
  76.  **                                                                             **
  77.  *****************************************************************************/
  78.  
  79. /*===========================================================================*\
  80.  *
  81.  *    Routine:    ErQDWindow_New()
  82.  *
  83.  *    Comments:    Create a Quickdraw window and return it.  The window is
  84.  *                centered in the gdevice that has the specified depth or
  85.  *                the device with the greatest depth less than said depth.
  86.  *
  87.  *    Notes:        This is an applicatiion specific function.
  88.  *
  89. \*===========================================================================*/
  90.  
  91. WindowPtr QDWindow_New(
  92.     Str255            name,
  93.     unsigned long    x,
  94.     unsigned long    y,
  95.     unsigned long    xSize, 
  96.     unsigned long    ySize, 
  97.     unsigned long    depth,
  98.     TQ3Boolean        autoCenter)
  99. {
  100.     Rect            deviceBounds;
  101.     unsigned short    xCenter;
  102.     unsigned short    yCenter;
  103.     Rect            where;
  104.     GDHandle        gDevice;
  105.     WindowPtr        window;
  106.  
  107.     gDevice = GetGDeviceUsingDepth(depth);
  108.     deviceBounds = (*gDevice)->gdRect;
  109.     
  110.     if (autoCenter) {
  111.         xCenter = deviceBounds.left + ((deviceBounds.right - deviceBounds.left)/2);
  112.         yCenter = deviceBounds.top + ((deviceBounds.bottom - deviceBounds.top)/2);
  113.         yCenter += (GetMBarHeight()/2);
  114.     
  115.         where.left         = xCenter - (xSize/2);
  116.         where.top         = yCenter - (ySize/2);
  117.     } else {
  118.         where.left         = x;
  119.         where.top         = y;
  120.     }
  121.  
  122.     where.right     = where.left + xSize;
  123.     where.bottom     = where.top + ySize;
  124.  
  125.     window = NewCWindow(nil, 
  126.                         &where, 
  127.                         name, 
  128.                         true, 
  129.                         documentProc, 
  130.                         (WindowPtr) -1, 
  131.                         false, 
  132.                         0);
  133.     if (!window) {
  134.         return (NULL);
  135.     }
  136.     
  137.     SetPort(window);
  138.     
  139.     return (window);
  140. }
  141.  
  142.  
  143. /*===========================================================================*\
  144.  *
  145.  *    Routine:    GetGDeviceUsingDepth()
  146.  *
  147.  *    Comments:    Find the gdevice that best fits the depth argument.  If not
  148.  *                found then return the first gdevice.
  149.  *
  150.  *    Notes:        This is an applicatiion specific function.
  151.  *
  152. \*===========================================================================*/
  153.  
  154. static GDHandle GetGDeviceUsingDepth(
  155.     unsigned long    depth)
  156. {
  157.     GDHandle        device;                /* current device */
  158.     GDHandle        bestDevice;            /* device close to matching depth */
  159.     unsigned long    bestDeviceNotFound;    /* termination flag */
  160.  
  161.     bestDevice = device = GetDeviceList();
  162.     bestDeviceNotFound = 1;
  163.  
  164.     while (bestDeviceNotFound && device) {
  165.         /* only search on active screen devices */
  166.         if (((*device)->gdFlags & (1 << screenActive)) == 0) {
  167.             continue;
  168.         }
  169.  
  170.         if ((*(*device)->gdPMap)->pixelSize == depth) {
  171.             bestDevice = device;
  172.             bestDeviceNotFound = 0;
  173.         }
  174.         
  175.         device = GetNextDevice(device);
  176.     }
  177.  
  178.     return (bestDevice);
  179. }
  180.  
  181.  
  182. /*===========================================================================*\
  183.  *
  184.  *    Routine:    ErQDGWorld_New()
  185.  *
  186.  *    Comments:    Create a Quickdraw window and return it.  The window is
  187.  *                centered in the gdevice that has the specified depth or
  188.  *                the device with the greatest depth less than said depth.
  189.  *
  190.  *    Notes:        This is an applicatiion specific function.
  191.  *
  192. \*===========================================================================*/
  193.  
  194. GWorldPtr QDGWorld_New(
  195.     unsigned long    xSize, 
  196.     unsigned long    ySize, 
  197.     unsigned long    depth)
  198. {
  199.     Rect            rectGW;
  200.     GWorldPtr        gWorld;
  201.     PixMapHandle     hPixMap;
  202.     
  203.     SetRect(&rectGW, 0, 0, (unsigned short)xSize, (unsigned short)ySize);
  204.     NewGWorld(&gWorld, depth, &rectGW, 0, 0, 0);
  205.     
  206.     if(gWorld == NULL)
  207.         return(NULL);
  208.  
  209.     hPixMap = GetGWorldPixMap(gWorld);
  210.     HLock((Handle)hPixMap);
  211.  
  212.     LockPixels(hPixMap);
  213.  
  214.     HUnlock((Handle)hPixMap);
  215.     
  216.     return (gWorld);
  217. }
  218.  
  219.  
  220. /*===========================================================================*\
  221.  *
  222.  *    Routine:    QDClearBackground()
  223.  *
  224.  *    Comments:    
  225.  *
  226.  *    Notes:        This is an applicatiion specific function.
  227.  *
  228. \*===========================================================================*/
  229.  
  230. void QDClearBackground(
  231.     GWorldPtr    gWorld,
  232.     TQ3ColorRGB    bgColor)
  233. {
  234.     RGBColor    qdBgColor;
  235.     GrafPtr        thePort;
  236.  
  237.     if (gWorld) {
  238.         GDHandle    oldGD;
  239.         GWorldPtr    oldGW;
  240.  
  241.         /* save current port */
  242.         GetGWorld(&oldGW, &oldGD);
  243.  
  244.         SetGWorld(gWorld, NULL);
  245.         qdBgColor.red     = (unsigned short)(bgColor.r * 65535.0);
  246.         qdBgColor.green = (unsigned short)(bgColor.g * 65535.0);
  247.         qdBgColor.blue     = (unsigned short)(bgColor.b * 65535.0);
  248.         RGBBackColor(&qdBgColor);
  249.         EraseRect(&gWorld->portRect);
  250.         
  251.         /* restore port */
  252.         SetGWorld(oldGW, oldGD);
  253.     } else {
  254.         qdBgColor.red     = (unsigned short)(bgColor.r * 65535.0);
  255.         qdBgColor.green = (unsigned short)(bgColor.g * 65535.0);
  256.         qdBgColor.blue     = (unsigned short)(bgColor.b * 65535.0);
  257.         RGBBackColor(&qdBgColor);
  258.         GetPort(&thePort);
  259.         EraseRect(&thePort->portRect);
  260.     }
  261. }
  262.  
  263.  
  264. /*===========================================================================*\
  265.  *
  266.  *    Routine:    ErQDSwapBuffer()
  267.  *
  268.  *    Comments:    If there is a gWorld then copy from it to the window.
  269.  *
  270.  *    Notes:        This is an applicatiion specific function.
  271.  *
  272. \*===========================================================================*/
  273.     
  274. void QDSwapBuffer(
  275.     WindowPtr    window,
  276.     GWorldPtr    gWorld)
  277. {
  278.     if (window && gWorld) {
  279.         PixMapHandle     hPixMap;
  280.         GrafPtr            savePort;
  281.         RGBColor        qdBgColor;
  282.         
  283.         GetPort(&savePort);
  284.         SetPort(window);
  285.         
  286.         hPixMap = GetGWorldPixMap(gWorld);
  287.         HLock((Handle)hPixMap);
  288.  
  289.         qdBgColor.red     = (unsigned short)65535;
  290.         qdBgColor.green = (unsigned short)65535;
  291.         qdBgColor.blue     = (unsigned short)65535;
  292.         RGBBackColor(&qdBgColor);
  293.  
  294.         /* myGDevice = FindDeviceFromWindow(window, hPixMap); */
  295.         /* CopyPixels_32(myGDevice, window, hPixMap); */
  296.         CopyBits((BitMapPtr)(*hPixMap), 
  297.                  (BitMapPtr) &window->portBits,
  298.                  (Rect *) &(*gWorld).portRect,
  299.                  (Rect *) &window->portRect,
  300.                  (short)srcCopy, (RgnHandle)NULL);    
  301.  
  302.         HUnlock((Handle)hPixMap);
  303.         
  304.         SetPort(savePort);
  305.     }
  306. }
  307.  
  308. /*===========================================================================*\
  309.  *
  310.  *    Routine:    CopyPixels_32()
  311.  *
  312.  *    Comments:
  313.  *
  314. \*===========================================================================*/
  315.  
  316. static void CopyPixels_32(
  317.     GDHandle        device,
  318.     WindowPtr        window,
  319.     PixMapHandle    hPixMap)
  320. {
  321.     long            w, width, height;
  322.     Point            upperLeft;
  323.     Rect            deviceBounds;
  324.     long            offsetX, offsetY;
  325.     unsigned long    *srcPtr, *srcStart, *dstPtr, *dstStart;
  326.     long            srcRowBytes, dstRowBytes;
  327.  
  328.     width = (*hPixMap)->bounds.right - (*hPixMap)->bounds.left;
  329.     height = (*hPixMap)->bounds.bottom - (*hPixMap)->bounds.top;
  330.  
  331.     upperLeft.v = window->portRect.top;
  332.     upperLeft.h = window->portRect.left;
  333.     LocalToGlobal(&upperLeft);
  334.  
  335.     deviceBounds = (*device)->gdRect;
  336.     offsetX = upperLeft.h - deviceBounds.left;    
  337.     offsetY = upperLeft.v - deviceBounds.top;
  338.  
  339.     srcRowBytes = (*hPixMap)->rowBytes & 0x3FFF;
  340.     dstRowBytes = (*(*device)->gdPMap)->rowBytes & 0x3FFF;
  341.     
  342.     srcStart = (unsigned long *)(*hPixMap)->baseAddr;
  343.  
  344.     dstStart = (unsigned long *)((unsigned char *)((*(*device)->gdPMap)->baseAddr) +
  345.         (offsetY * dstRowBytes) + (offsetX << 2));
  346.  
  347.     while (--height >= 0) {
  348.         w = width;
  349.  
  350.         srcPtr = srcStart;
  351.         dstPtr = dstStart;
  352.  
  353.         while (--w >= 0) {
  354.             *dstPtr++ = *srcPtr++;
  355.         }
  356.  
  357.         srcStart = (unsigned long *)((unsigned char *)srcStart + srcRowBytes);
  358.         dstStart = (unsigned long *)((unsigned char *)dstStart + dstRowBytes);
  359.     }
  360. }
  361.  
  362. /*===========================================================================*\
  363.  *
  364.  *    Routine:    FindDeviceFromWindow()
  365.  *
  366.  *    Comments:
  367.  *
  368. \*===========================================================================*/
  369.  
  370. static GDHandle FindDeviceFromWindow(
  371.     WindowPtr         window,
  372.     PixMapHandle     hPixMap)
  373. {
  374.     GDHandle        device;            /* current device */
  375.     Rect            devBox;            /* local coords of device intersected with drawBox */
  376.     Point            topLeft;        /* topLeft of current port */
  377.     RgnHandle        devRgn;            /* region for device rectangle */
  378.     RgnHandle        drawRgn;        /* region for draw box */
  379.     RgnHandle        dstRgn;            /* intersect of drawing and device regions */
  380.     Rect            drawBox;        /* drawing rectangle */
  381.  
  382.     if (!window) {
  383.         return (NULL);
  384.     }
  385.  
  386.     devRgn = NewRgn();
  387.     HLock((Handle)devRgn);
  388.     drawRgn = NewRgn();
  389.     HLock((Handle)drawRgn);
  390.     dstRgn = NewRgn();
  391.     HLock((Handle)dstRgn);
  392.     
  393.     drawBox = window->portRect;
  394.  
  395.     GetPortTopLeft((CGrafPtr)window, &topLeft);
  396.     SetRectRgn(drawRgn, 
  397.                drawBox.left, drawBox.top, 
  398.                drawBox.right, drawBox.bottom);
  399.     
  400.     device = GetDeviceList();
  401.  
  402.     while (device) {
  403.         if (((*device)->gdFlags & (1 << screenActive))) {
  404.             /* convert the device rect to local coordinates */
  405.             COPYRECT(&(*device)->gdRect, &devBox);
  406.             devBox.top    -= topLeft.v;
  407.             devBox.left   -= topLeft.h;
  408.             devBox.bottom -= topLeft.v;
  409.             devBox.right  -= topLeft.h;
  410.             
  411.             /* test for intersection */
  412.             SetRectRgn(devRgn, 
  413.                        devBox.left, devBox.top, 
  414.                        devBox.right, devBox.bottom);
  415.             SectRgn(devRgn, drawRgn, dstRgn);
  416.  
  417.             if (!EmptyRgn(dstRgn)) {
  418.                 PixMapHandle    gdPMap;
  419.                 
  420.                 gdPMap = (*device)->gdPMap;
  421.                 if ((*gdPMap)->pixelSize == (*hPixMap)->pixelSize) {
  422.                     goto GetOutOfThisFunction;
  423.                 }
  424.  
  425.             }
  426.         }
  427.  
  428.         device = GetNextDevice(device);
  429.         
  430.     }
  431.         
  432. GetOutOfThisFunction:
  433.  
  434.     HUnlock((Handle)devRgn);
  435.     HUnlock((Handle)drawRgn);
  436.     HUnlock((Handle)dstRgn);
  437.     DisposeRgn(devRgn);
  438.     DisposeRgn(dstRgn);
  439.     DisposeRgn(drawRgn);
  440.     
  441.     return (device);
  442. }
  443.  
  444. /*===========================================================================*\
  445.  *
  446.  *    Routine:        GetPortTopLeft(port, topLeft)
  447.  *
  448.  *    Comments:        returns the 0,0 of the port in global coordinates
  449.  *
  450. \*===========================================================================*/
  451.  
  452. static void GetPortTopLeft(
  453.     CGrafPtr     port, 
  454.     Point         *topLeft)
  455. {
  456.     BitMap         *bits;
  457.     
  458.     bits = BitsToMap(&((GrafPtr) port)->portBits);
  459.     
  460.     topLeft->v = - bits->bounds.top;
  461.     topLeft->h = - bits->bounds.left;
  462. }
  463.  
  464.  
  465. /*===========================================================================*\
  466.  *
  467.  *    Routine:        BitsToMap(bits)
  468.  *
  469.  *    Comments:        if bits is the address of portBits of a cgrafport then
  470.  *                    convert it to a pointer to the port's pix map.
  471.  *
  472. \*===========================================================================*/
  473.  
  474. static BitMap *BitsToMap(
  475.     BitMap     *bits)
  476. {
  477.     if (((BitMap *)bits)->rowBytes < 0 &&
  478.         ((BitMap *)bits)->rowBytes & (1 << 14)) {
  479.         bits = *(BitMap **) bits->baseAddr;
  480.     }
  481.     
  482.     return bits;
  483. }
  484.